<?php

/* This is a really simple text formatter.
I would really like to replace it with a yacc parser
*/
if(defined("_PARA_FORUM_TEXTFORMATTER"))
    return;
define("_PARA_FORUM_TEXTFORMATTER", 1);

define ( TF_TEXT,  1 );
define ( TF_HEAD1, 2 );
define ( TF_HEAD2, 3 );
define ( TF_ULIST, 4 );
define ( TF_OLIST, 5 );

require_once "HTMLable.php";
class TextFormatter extends HTMLable {

    public $text   = '';
    public $blocks = array();
    public $main_class = 'para_ftext';
    public static $smileys;



    public function TextFormatter( $text ) {
        $text =  preg_replace('/[\r]/', '', $text );
        $lines = preg_split( '/\n/', $text );

        $last_empty    = true;
        $cur_text       = '';

        foreach( $lines as $line ) {
            $line = trim( $line );
            if( preg_match('/^\s*$/', $line )) {
                $cur_text = $this->_finish_text_block( $cur_text );
            }
            elseif(preg_match('/^==(.*)==$/', $line, $matches )) {
                $cur_text = $this->_finish_text_block( $cur_text );
                array_push( $this->blocks, TF_HEAD1, $matches[1] );
            }
            elseif(preg_match('/^=(.*)=$/', $line, $matches )) {
                $cur_text = $this->_finish_text_block( $cur_text );
                array_push( $this->blocks, TF_HEAD2, $matches[1] );
            }
            elseif(preg_match('/^#(.*)$/', $line, $matches )) {
                $cur_text = $this->_finish_text_block( $cur_text );
                array_push( $this->blocks, TF_OLIST, $matches[1] );
            }
            elseif(preg_match('/^\*[^\*](.*)$/', $line, $matches )) {
                $cur_text = $this->_finish_text_block( $cur_text );
                array_push( $this->blocks, TF_ULIST, $matches[1] );
            }
            else {
                $cur_text .= ' '. $line;
            }
        }
        $this->_finish_text_block( $cur_text );



    }

    private function _finish_text_block( $text ) {
        if(strlen($text))
            array_push( $this->blocks, TF_TEXT, $text );
        return '';
    }


    public function dump() {
        $blk = $this->blocks;
        for( $i = 0; $i<sizeof($blk); ) {
            echo "TYPE : $blk[$i]\n";
            echo $blk[ $i+1 ] , "\n=======\n";
            $i+=2;
        }
    }

    public function htmlize( $options ) {
       $blk = $this->blocks;
       $cur_ul = null;
       $cur_ol = null;
       $id_tag = '';
       if( $options['id'] )
           $id_tag = ' id="' . $options['id'] . '"';

       echo '<div class="' . $this->main_class . "\"$id_tag>\n";
       for( $i = 0; $i<sizeof($blk); ) {
           switch($blk[$i]) {
           case TF_HEAD1:
               $i = $this->htmlize_head( $i ); break;
           case TF_HEAD2:
               $i = $this->htmlize_head( $i ); break;
           case TF_TEXT:
               $i = $this->htmlize_text( $i ); break;
           case TF_ULIST: 
               $i = $this->htmlize_ulist( $i ); break;              
           case TF_OLIST: 
               $i = $this->htmlize_olist( $i ); break;              
           default:
               echo "WTF " . $blk[$i] ."?\n"; $i+=2; break;
           }
       }
       echo "</div>\n";

   }

    private function htmlize_ulist( $i ) {
        $blk = $this->blocks;
        echo '<ul class="'. $this->main_class . '_ul">' ."\n";
        while( $i < sizeof($blk) ) {
            if($blk[$i] != TF_ULIST )
                break;
            echo '<li class="'. $this->main_class . '_ul_item">';
            echo htmlspecialchars( $blk[$i+1]);
            echo "</li>\n";
            $i += 2;
        }
        echo '</ul>';
        return $i;
    }


    private function htmlize_olist( $i ) {
        $blk = $this->blocks;
        echo '<ol class="'. $this->main_class . '_ol">' . "\n";
        while( $i < sizeof($blk) ) {
            if($blk[$i] != TF_OLIST )
                break;
            echo '<li class="'. $this->main_class . '_ol_item">';
            echo htmlspecialchars( $blk[$i+1]);
            echo "</li>\n";
            $i += 2;
        }
        echo '</ol>';
        return $i;
    }

    private function htmlize_head( $i ) {
        $type    = $this->blocks[$i];
        $content = $this->blocks[$i+1];

        if($type == TF_HEAD1)
            echo '<div class="'. $this->main_class . '_head1">';
        else
            echo '<div class="'. $this->main_class . '_head2">';

        echo htmlspecialchars( $content ), "</div>\n";

        return $i+2;
    }


    private function htmlize_text( $i ) {
        $content = $this->blocks[$i+1];
        echo '<div class="'. $this->main_class . '_text">';

        echo TextFormatter::format_text( $content );
        echo "</div>\n";

        return $i+2;
    }


    public static function format_link( $matches ) {
        $unsafe_link = preg_replace('/&amp;/', '&', $matches[1]);
        return '<a href="' . $unsafe_link . '">' . $matches[1] . '</a>';
    }


    public static function format_text( $content ) {
        $content = htmlspecialchars( $content );

        // bold text is marked as *bold*
        $content = preg_replace('/\*{2}([^\*]+?)\*{2}/', '<b>$1</b>', $content );
        // italics is marked as //italic//
        $content = preg_replace('/\/{2}([^\/]+?)\/{2}/', '<i>$1</i>', $content );
        // underline is marked as --underlined--
        $content = preg_replace('/__([^_]+?)__/', '<u>$1</u>', $content );
        // striked text marked as --striked--
        $content = preg_replace('/\-\-([^_]+?)\-\-/', '<del>$1</del>', $content );

        foreach(TextFormatter::$smileys as $smiley => $imgfile ) {
            $content = str_replace( $smiley, "<img src=\"images/$imgfile\" />", $content );
        }

        // will use preg_replace_callback here soon..... FIXME
        //$content = preg_replace('/\[\[(.*?)\]\]/', '<a href="$1">Link</a>', $content );
        $content = preg_replace_callback('/\[\[(.*?)\]\]/', 'TextFormatter::format_link', $content );

        return $content;
    }

}

TextFormatter::$smileys = 
    array( ':)'  => 'sm_smile.gif',
           ':-)' => 'sm_smile.gif',
           ':('  => 'sm_frown.gif',
           ':-(' => 'sm_frown.gif',
           ':o'  => 'sm_redface.gif',
           ';)'  => 'sm_wink.gif',
           ':D'  => 'sm_biggrin.gif',
           ':-@' => 'sm_mad.gif',
           ':@'  => 'sm_mad.gif',
           ':S'  => 'sm_confused.gif',
           ':s'  => 'sm_confused.gif',
           '8-)' => 'sm_cool.gif',
        );


